package org.caffinitas.ohc.gossip.webclient;

import org.caffinitas.ohc.OHCache;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;

public class Server<K> {
    // 选择器
    private Selector selector;
    // 连接通道
    private ServerSocketChannel listenChannel;

    private OHCache cache;

    public Server(int port) {
        try {
            selector = Selector.open();
            listenChannel = ServerSocketChannel.open();
            // 绑定端口
            listenChannel.socket().bind(new InetSocketAddress(port));
            // 设置非阻塞模式
            listenChannel.configureBlocking(false);
            // 连接注册到selector
            listenChannel.register(selector, SelectionKey.OP_ACCEPT);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void listen() {
        System.out.println("服务端正在监听.........");
        try {
            while (true) {
                // 获取事件
                if (selector.select() == 0) {
                    continue;
                }
                Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                while (iterator.hasNext()) {
                    SelectionKey key = iterator.next();
                    // 监听到不同的事件进行不同的处理
                    listenHandler(key);
                    // 删除当前key，防止重复处理
                    iterator.remove();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 针对监听到的不同事件做不同的处理
     */
    public void listenHandler(SelectionKey key) {
        SocketChannel sc = null;
        try {
            // 连接事件处理
            if (key.isAcceptable()) {
                // 连接注册到selector
                sc = listenChannel.accept();
                sc.configureBlocking(false);
                sc.register(selector, SelectionKey.OP_READ);
            }
            // 读取事件处理
            if (key.isReadable()) {
                // 拿到socketChannel
                sc = (SocketChannel) key.channel();
                sc.configureBlocking(false);
                ByteBuffer buffer = ByteBuffer.allocate(1024);
                // 读取消息数据
                if (sc.read(buffer) > 0) {
                    String msg = new String(buffer.array());
                    System.out.println("转发消息: " + msg);
                    // 将消息转发
                    sendMsgToClient(msg);
                }
            }
        } catch (IOException e) {
            try {
                // 取消注册
                key.cancel();
                // 关闭通道
                sc.close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
    }

    /**
     * 发送消息到客户端
     */
    public void sendMsgToClient(String msg) throws IOException {
        for (SelectionKey key : selector.keys()) {
            Channel channel = key.channel();
            if (channel instanceof SocketChannel) {
                SocketChannel targetChannel = (SocketChannel) channel;
                // 将msg写到buffer中
                ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes());
                // 将buffer数据写入通道
                targetChannel.write(buffer);
            }
        }
    }

    public static void main(String[] args) {
        Server server = new Server(8088);
        server.listen();
    }

}
